<script setup lang="ts">
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue';
import { useDebounceFn } from '@vueuse/core';
import { onBeforeRouteLeave } from 'vue-router';
import localForage from 'localforage';
import { router } from '@/router';
import { fetchPreview } from '@/service/api';
import Content from './_modules/_content/index.vue';
import Sider from './_modules/_sider/index.vue';
import { useStore } from './store';
import Toolbar from './_modules/_content/toolbar.vue';

const store = useStore();
// 重置 store
// 播放文本
const playText = ref<string>(store.text);
watch(
  () => store.text,
  newVal => {
    playText.value = newVal;
  }
);
const playTextMax = ref<number>(1000);
const flag = ref<boolean>(false);
// 输入时更新store 存储
const updateText = useDebounceFn(updateTextFn, 3000);
const query = computed(() => router.currentRoute.value.query);
const isHorizontal = computed(() => store.canvasConfig.direction === 'horizontal');
console.log(query, 'query');
function updateTextFn() {
  store.updateText(playText.value);
  flag.value = true;
  setTimeout(() => {
    flag.value = false;
  }, 3000);
}

const toList = () => {
  router.replace('product-list');
};

// 预览 - 调弹窗
const contentRef = ref<any>(null);

const preview = reactive<any>({
  visible: false,
  loading: false,
  audioLoading: false,
  cover: '', // 封面路径
  audioRef: null,
  show: async () => {
    preview.visible = true; // 先打开
    if (contentRef.value) {
      try {
        preview.src = '';
        preview.loading = true;
        preview.audioLoading = true;

        await Promise.all([contentRef.value.canvasExportCover()]).then(async ([imageUrl]) => {
          console.log('=========获取到了图片了');
          // 获取当前域名
          const domain = window.location.origin;
          // 获取视频
          const res = await fetchPreview({
            text: playText.value.slice(0, 50),
            id: store.voice.id,
            imageUrl: `${domain}${imageUrl}`,
            isLandscape: isHorizontal.value,
            width: store.canvasConfig.width,
            height: store.canvasConfig.height
          });
          console.log(res, 'res');
          if (imageUrl) {
            preview.cover = imageUrl;
            preview.videoUrl = res.data.url;
            preview.audioLoading = false;
          }
        });
      } catch (_error) {
        window.$message?.warning('预览加载失败');
      } finally {
        preview.loading = false;
      }
    }
  },
  close: async () => {
    preview.visible = false;
    preview.videoUrl = '';
  }
});

// 导出
async function onExport(isSave: boolean) {
  if (!isSave) {
    // 判断有没有输入
    if (playText.value.length < 5) {
      window.$message?.error('请输入至少5个字符的播报文本');
      return;
    }
  }
  exportModal.isSave = isSave;
  exportModal.visible = true;
}

// 更新标识 记录是否有操作 => 无操作可以直接退出
const updateFlag = computed(() => {
  return store.updateFlag;
});
const exportModal = reactive<any>({
  visible: false,
  isSaveLoading: false,
  isSubmitLoading: false,
  id: query.value.id, // creation id // 保存+更新+导出 用的
  detailId: query.value.detailId, // 查详情用的
  name: query.value.videoName || '', // 任务名称
  resolution: '720P', // 规格
  selected: async (value: string) => {
    exportModal.resolution = value;
    await contentRef.value.canvasExportCover();
  },
  submit: async () => {
    if (!exportModal.name) {
      window.$message?.error('请输入视频名称');
      return;
    }

    // 没有预览图就生成 || 有了是否需要更新一下，但要上传，耗时。
    // if (!store.cover) {
    // await contentRef.value.canvasExportCover(); // 已存 store.cover
    // }

    // 保存按钮
    if (exportModal.isSave) {
      exportModal.isSaveLoading = true;
      await contentRef.value.canvasExportFn(); // 已存 store.cover
      try {
        await contentRef.value.canvasExportCover(); // 已存 store.cover
      } catch (error) {
        window.$message?.error(`保存封面失败，${error}`);
        exportModal.isSaveLoading = false;
        return;
      }
      let result: any;
      // 保草稿
      if (!exportModal.id)
        result = await store.saveTask({
          status: 0,
          name: exportModal.name,
          resolution: exportModal.resolution,
          playText: playText.value
        });
      // 提交任务接口 传状态（草稿 0） | videoName | 分辨率 720P
      // else result = await store.saveTask(0, exportModal.name, exportModal.resolution, exportModal.id); // 更新草稿 + id
      else
        result = await store.saveTask({
          status: 0,
          name: exportModal.name,
          resolution: exportModal.resolution,
          id: exportModal.id,
          playText: playText.value
        }); // 更新草稿 + id

      if (result) {
        exportModal.id = result;
        store.toggleUpdateFlag(false); // 当前未更新
      }
      window.$message?.success('保存成功');
      exportModal.isSaveLoading = false;
      exportModal.visible = false;
      setTimeout(async () => {
        // 返回列表&计时任务
        intercepModal.path = 'product-list';
        intercepModal.cancel();
        store.reset();
      }, 100);
    } else {
      exportModal.isSubmitLoading = true;
      try {
        await contentRef.value.canvasExportFn(); // 已存 store.cover
        try {
          await contentRef.value.canvasExportCover(); // 已存 store.cover
        } catch (error) {
          window.$message?.error(`保存封面失败，${error}`);
          exportModal.isSubmitLoading = false;
          return;
        }
        // 1, exportModal.name, exportModal.resolution
        let result: any;
        if (!exportModal.id) {
          result = await store.saveTask({
            status: 1,
            name: exportModal.name,
            resolution: exportModal.resolution,
            playText: playText.value
          }); // 提交任务接口 传状态（导出 1） | videoName | 分辨率 720P
        } else {
          result = await store.saveTask({
            status: 1,
            name: exportModal.name,
            resolution: exportModal.resolution,
            id: exportModal.id,
            playText: playText.value
          }); // 提交任务接口 传状态（导出 1） | videoName | 分辨率 720P
        }

        if (result) {
          if (!exportModal.id) exportModal.id = result;
          window.$message?.success('视频已导出，请在列表查看');

          const creatingList = (await localForage.getItem<{ id: number; eat: number }[]>('creatingList')) || [];

          await localForage.setItem('creatingList', [
            ...creatingList,
            { id: result, eat: (playText.value.length * 140) / 1000 + 5 }
          ]);

          setTimeout(async () => {
            // 返回列表&计时任务
            store.reset();
            intercepModal.path = 'product-list';
            console.log('intercepModal.path', intercepModal.path);
            intercepModal.cancel();
          }, 1000);
          return;
        }
        window.$message?.error('视频导出失败');
      } finally {
        exportModal.isSubmitLoading = false;
        exportModal.visible = false;
      }
    }
  },
  reset: () => {
    const checkLoading = () => {
      if (exportModal.isSaveLoading || exportModal.isSubmitLoading) {
        setTimeout(checkLoading, 100);
        return;
      }
      exportModal.resolution = '720P';
      exportModal.name = query.value.videoName || '';
    };
    checkLoading();
  }
});

// 路由拦截
const intercepModal = reactive({
  visible: false,
  isOk: false,
  isSave: false,
  loading: false,
  content: '',
  btnText: '',
  path: '',
  enter: async () => {
    intercepModal.loading = true;
    try {
      await contentRef.value.canvasExportCover(); // 已存 store.cover
    } catch (error) {
      window.$message?.error(`保存封面失败，${error}`);
      intercepModal.loading = false;
      return;
    }
    // 保存草稿
    contentRef.value.canvasExportFn(); // 已存 store.cover
    const name: any = query.value.videoName || `视频草稿`;
    const result = await store.saveTask({
      status: 0,
      name,
      resolution: exportModal.resolution,
      id: query.value.id as any,
      playText: playText.value
    }); // 提交任务接口 传状态（导出 1） | videoName | 分辨率 720P
    result && window.$message?.success('保存成功');
    // 保存失败也退出
    intercepModal.loading = false;
    intercepModal.visible = false;
    intercepModal.isOk = true;
    intercepModal.content = '';
    intercepModal.btnText = '';
    store.reset(); // 清空store
    router.replace(intercepModal.path);
  },
  cancel: () => {
    intercepModal.isOk = true;
    intercepModal.visible = false;
    store.reset(); // 清空store
    router.replace(intercepModal.path);
  },
  show: (to: any) => {
    console.log(to.path, 'to.path');
    intercepModal.path = to.path;
    intercepModal.visible = true;
    intercepModal.content = '若不保存，系统不会保存您所做的更改。';
    intercepModal.btnText = '取消';
  }
});

// 路由拦截钩子
onBeforeRouteLeave((to, _from, next) => {
  // 已确定 || 未更新  = 放行
  console.log('intercepModal.isOk', intercepModal.isOk);
  console.log('updateFlag.value', updateFlag.value);
  if (intercepModal.isOk || !updateFlag.value) {
    next();
  } else {
    console.log('路由拦截，展示弹窗');
    intercepModal.show(to);
    next(false);
  }
});

// 浏览器刷新行为控制
function stopF5Refresh() {
  document.onkeydown = evt => {
    // 屏蔽F1---F12
    if (evt.key && evt.key.startsWith('F') && !Number.isNaN(Number.parseInt(evt.key.slice(1), 10))) {
      evt.preventDefault();
    }
  };
  // 禁止鼠标右键菜单
  document.oncontextmenu = () => {
    return false;
  };
}
stopF5Refresh(); // 1. created

function handleBeforeUnload(e: any) {
  // 设置 e.returnValue 来触发默认的离开页面确认对话框
  e.returnValue = '你好';
}
onMounted(() => {
  if (query.value.detailId) {
    store.getDraftInfo(query.value.detailId as string);
  }

  store.init(); // 初始化素材选项值

  // 2. 浏览器刷新行为拦截注册
  window.addEventListener('beforeunload', handleBeforeUnload);
});

onUnmounted(() => {
  window.removeEventListener('beforeunload', handleBeforeUnload);
});

const getTime = (length: number) => {
  return `${((length * 140) / 1000).toFixed(1)}s`;
};
</script>

<template>
  <div class="relative wh-full">
    <header class="header-bar">
      <div class="w-25% flex">
        <NButton class="mr-6 !w-16 !rounded-2" @click="toList">
          <SvgIcon class="text-6 text-siderbar_text hover:!text-primary" icon="ion:arrow-back-outline"></SvgIcon>
        </NButton>
        <SystemLogo />
      </div>
      <div class="text-4 text-base_text">{{ query.videoName || '未命名' }}</div>
      <div class="w-25% flex justify-end">
        <Toolbar />
        <NButton :disabled="!playText.length" type="default" secondary class="mr-4" @click="preview.show()">
          <SvgIcon class="mr-1 text-6 text-siderbar_text -ml-1" icon="material-symbols:play-arrow-rounded"></SvgIcon>
          预览
        </NButton>
        <NButton type="primary" color="#675EE1" class="!text-white" @click="onExport(false)">导出视频</NButton>
        <NButton type="primary" color="#675EE1" class="ml-4 !text-white" @click="onExport(true)">保存</NButton>
      </div>
    </header>
    <main class="main-container">
      <NFlex :size="0" :wrap="false" justify="space-between" class="h-full bg-siderbar">
        <!-- 侧边栏 -->
        <Sider class="h-full w-100 flex-shrink-0" />
        <!-- 画布区域 -->
        <Content
          ref="contentRef"
          class="relative flex-grow-1 border border-b-0 border-t-0 border-header border-solid bg-layout pt-20"
        />
        <NFlex vertical :size="0" class="h-full w-100 px-4 pb-4">
          <NFlex class="h-17.5" align="center" justify="space-between">
            <p class="flex-y-center text-4 text-base_text">
              播报文本
              <span
                :class="{
                  'opacity-100': flag
                }"
                class="ml-2 mt-1 flex-y-center text-3 text-light_text opacity-0 transition-opacity"
              >
                <SvgIcon icon="ion:md-checkmark-circle-outline" class="mr-0.5" />
                已自动保存
              </span>
            </p>
            <p class="text-3 text-light_text">
              {{ playText.length }}/{{ playTextMax }}
              <span v-if="playText.length">约 {{ getTime(playText.length) }}</span>
            </p>
          </NFlex>
          <NInput
            v-model:value="playText"
            placeholder="输入播报的文本"
            :maxlength="playTextMax"
            class="h-[calc(100%-70px)] border border-content_hover border-solid bg-transparent !text-3.5"
            type="textarea"
            size="large"
            autosize
            @update:value="updateText"
          />
        </NFlex>
      </NFlex>
    </main>

    <!-- 回退弹窗拦截 -->
    <NModal
      v-model:show="intercepModal.visible"
      preset="dialog"
      :auto-focus="false"
      class="rd-4 bg-header"
      title="是否保存当前内容？"
      :content="intercepModal.content"
      :loading="intercepModal.loading"
      :mask-closable="false"
      :closable="false"
    >
      <p class="">若不保存，系统不会保存您所做的更改。</p>
      <div class="flex-y-center justify-end">
        <NButton
          :disabled="intercepModal.loading"
          type="default"
          size="small"
          class="mr-4"
          @click="intercepModal.cancel"
        >
          取消
        </NButton>
        <NButton
          type="primary"
          :disabled="intercepModal.loading"
          :loading="intercepModal.loading"
          color="#675EE1"
          size="small"
          class="!text-white"
          @click="intercepModal.enter"
        >
          保存
        </NButton>
      </div>
    </NModal>

    <!-- 预览视频 -->
    <NModal
      v-model:show="preview.visible"
      :auto-focus="false"
      class="w-118 !bg-transparent !p-0 !shadow-none"
      :class="{
        'w-200': store.canvasConfig.size === '16:9'
      }"
      preset="card"
      display-directive="if"
      :mask-closable="false"
      @after-leave="preview.close"
    >
      <template #header>
        <div class="rd-2 bg-header p-4">
          <p class="flex-y-center text-3.5 text-base_text font-300">
            <SvgIcon icon="line-md:alert-circle" class="mr-2 text-5 text-#e54a45"></SvgIcon>
            预览状态数字人为静态画面，仅校对效果
          </p>
        </div>
      </template>
      <div class="card">
        <div class="card-img-wraper">
          <!-- <img src="@/assets/svg-icon/product/bg-3-4.svg" class="absolute-lt size-full object-cover" /> -->
          <!-- 加载 loading -->
          <div
            v-if="preview.audioLoading"
            class="absolute-lt z-1000 size-full flex-center animate-fade-in animate-duration-100"
          >
            <NSpin description="预览生成中..." size="large" />
          </div>
          <video v-if="preview.videoUrl" :src="preview.videoUrl" autoplay controls class="size-full object-cover" />
        </div>
      </div>
    </NModal>

    <!-- 导出视频 -->
    <NModal
      v-model:show="exportModal.visible"
      class="w-120 bg-header"
      preset="card"
      :auto-focus="false"
      display-directive="if"
      :close-on-esc="false"
      :mask-closable="false"
      :closable="exportModal.isSave ? !exportModal.isSaveLoading : !exportModal.isSubmitLoading"
      @after-leave="exportModal.reset"
    >
      <template #header>
        <p class="text-5 text-base_text font-500">{{ exportModal.isSave ? '保存视频' : '导出视频' }}</p>
      </template>
      <p class="mb-3 text-3.5">视频名称</p>
      <NInput v-model:value="exportModal.name" class="mb-6" maxlength="20" placeholder="请输入视频名称"></NInput>
      <template v-if="!exportModal.isSave">
        <p class="mb-3 text-3.5">选择分辨率</p>
        <div class="mb-8 flex-y-center justify-between">
          <div
            class="resolution-btn"
            :class="{
              '!border-primary !text-primary': exportModal.resolution === '720P',
              disabled: exportModal.isSave ? exportModal.isSaveLoading : exportModal.isSubmitLoading
            }"
            @click="
              exportModal.isSave
                ? exportModal.isSaveLoading
                : exportModal.isSubmitLoading
                  ? null
                  : exportModal.selected('720P')
            "
          >
            720P
          </div>
          <div
            class="resolution-btn"
            :class="{
              '!border-primary !text-primary': exportModal.resolution === '1080P',
              disabled: exportModal.isSave ? exportModal.isSaveLoading : exportModal.isSubmitLoading
            }"
            @click="
              exportModal.isSave
                ? exportModal.isSaveLoading
                : exportModal.isSubmitLoading
                  ? null
                  : exportModal.selected('1080P')
            "
          >
            1080P
          </div>
        </div>
      </template>

      <!-- 123 -->
      <div class="flex-y-center justify-end">
        <NButton
          type="default"
          class="!mr-2 !h-10 !w-22"
          :disabled="exportModal.isSave ? exportModal.isSaveLoading : exportModal.isSubmitLoading"
          @click="exportModal.visible = false"
        >
          取消
        </NButton>
        <NButton
          :disabled="!exportModal.name"
          :loading="exportModal.isSave ? exportModal.isSaveLoading : exportModal.isSubmitLoading"
          type="primary"
          color="#675EE1"
          class="!h-10 !w-22 !text-white"
          @click="exportModal.submit"
        >
          {{ exportModal.isSave ? '保存' : '导出' }}
        </NButton>
      </div>
    </NModal>
  </div>
</template>

<style scoped lang="scss">
$header-height: 64px;

.header-bar {
  height: $header-height;
  @apply w-full flex-y-center justify-between bg-header px-4;
}

.main-container {
  height: calc(100% - $header-height);
  @apply relative;
}

.resolution-btn {
  @apply h-10 w-52 flex-center cursor-pointer border-1 border-base_text/30 rd-1 transition-all border-solid text-base_text;

  &.disabled {
    @apply cursor-not-allowed opacity-50;
  }
}

// 预览卡片
$cardWidth: 400px;
$cardHeight: 705px;

.card {
  width: calc(100% - 24px);
  height: 100%;
  // width: $cardWidth;
  // height: $cardHeight;
  @apply relative transition-all-300 rounded-2 cursor-pointer overflow-hidden box-border;

  // 图片容器
  .card-img-wraper {
    width: 100%;
    height: 100%;
    min-height: 40vh;
    // width: $cardWidth;
    // height: $cardHeight;
    @apply relative rounded-2 overflow-hidden;
  }
}
</style>
